package xyz.zhno.mall.common.core.util;

import xyz.zhno.mall.common.core.enums.ErrorCodeEnum;
import xyz.zhno.mall.common.core.exception.APIException;

import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;

/**
 * 校验器
 * @author zh_o
 */
public class Validator {

    /**
     * 校验表达式是否为真，不为真则抛出指定异常
     * @param expression 校验的表达式
     * @param <X> 指定抛出的异常
     */
    public static <X extends Throwable> void isTrue(boolean expression, Supplier<X> errorSupplier) throws X {
        if (!expression) {
            throw errorSupplier.get();
        }
    }

    /**
     * 校验表达式是否为真，不为真则抛出异常
     * @param expression 校验的表达式
     * @param errorCode 错误码枚举
     */
    public static void isTrue(boolean expression, ErrorCodeEnum errorCode) {
        isTrue(expression, () -> new APIException(errorCode));
    }

    /**
     * 校验表达式是否为真，不为真则抛出异常
     * @param expression 校验的表达式
     */
    public static void isTrue(boolean expression) {
        isTrue(expression, ErrorCodeEnum.SERVER_ERROR);
    }

    /**
     * 校验表达式是否为真，不为真则抛出异常
     * @param expression 校验的表达式
     * @param code 抛出异常的错误码
     * @param message 抛出异常的message
     */
    public static void isTrue(boolean expression, String code, String message) {
        isTrue(expression, () -> new APIException(code, message));
    }

    /**
     * 校验表达式是否为真，不为真则抛出异常
     * @param expression 校验的表达式
     * @param message 抛出异常的message
     */
    public static void isTrue(boolean expression, String message) {
        isTrue(expression, "A5000", message);
    }

    /**
     * 校验表达式是否为真，不为真则抛出指定异常
     * @param expression 校验的表达式
     * @param <X> 指定抛出的异常
     */
    public static <X extends Throwable> void isFalse(boolean expression, Supplier<X> errorSupplier) throws X {
        if (expression) {
            throw errorSupplier.get();
        }
    }

    /**
     * 校验表达式是否为真，不为真则抛出异常
     * @param expression 校验的表达式
     * @param errorCode 错误码枚举
     */
    public static void isFalse(boolean expression, ErrorCodeEnum errorCode) {
        isFalse(expression, () -> new APIException(errorCode));
    }

    /**
     * 校验表达式是否为真，不为真则抛出异常
     * @param expression 校验的表达式
     */
    public static void isFalse(boolean expression) {
        isFalse(expression, ErrorCodeEnum.SERVER_ERROR);
    }

    /**
     * 校验表达式是否为真，不为真则抛出异常
     * @param expression 校验的表达式
     * @param code 抛出异常的错误码
     * @param message 抛出异常的message
     */
    public static void isFalse(boolean expression, String code, String message) {
        isFalse(expression, () -> new APIException(code, message));
    }


    /**
     * 校验表达式是否为真，不为真则抛出异常
     * @param expression 校验的表达式
     * @param message 抛出异常的message
     */
    public static void isFalse(boolean expression, String message) {
        isFalse(expression, "A5000", message);
    }

    /**
     * 校验对象是否为空，不为空则抛出指定异常
     * @param <T> 需要校验对象
     * @param <X> 抛出的指定异常
     */
    public static <T, X extends Throwable> T requireNull(T obj, Supplier<X> errorSupplier) throws X {
        isTrue(BeanUtils.isEmpty(obj), errorSupplier);
        return obj;
    }

    /**
     * 校验对象是否为空，不为空则抛出异常
     * @param obj 校验的对象
     * @param errorCode 错误码枚举
     */
    public static <T> T requireNull(T obj, ErrorCodeEnum errorCode) {
        isTrue(BeanUtils.isEmpty(obj), errorCode);
        return obj;
    }

    /**
     * 校验对象是否为空，不为空则抛出异常
     * @param obj 校验的对象
     */
    public static <T> T requireNull(T obj) {
        return requireNull(obj, ErrorCodeEnum.SERVER_ERROR);
    }

    /**
     * 校验对象是否为空，不为空则抛出异常
     * @param obj 校验的对象
     * @param code 抛出异常的错误码
     * @param message 抛出异常的message
     */
    public static <T> T requireNull(T obj, String code, String message) {
        return requireNull(obj, () -> new APIException(code, message));
    }

    /**
     * 校验对象是否为空，不为空则抛出异常
     * @param obj 校验的对象
     * @param message 抛出异常的message
     */
    public static <T> T requireNull(T obj, String message) {
        return requireNull(obj, "A5000", message);
    }

    /**
     * 校验对象是否不为空，为空则抛出指定异常
     * @param <T> 需要校验对象
     * @param <X> 抛出的指定异常
     */
    public static <T, X extends Throwable> T notNull(T obj, Supplier<X> errorSupplier) throws X {
        isFalse(BeanUtils.isEmpty(obj), errorSupplier);
        return obj;
    }

    /**
     * 是否不为空，为空则抛出异常
     * @param obj 校验的对象
     * @param errorCode 错误码枚举
     */
    public static <T> T notNull(T obj, ErrorCodeEnum errorCode) {
        isFalse(BeanUtils.isEmpty(obj), errorCode);
        return obj;
    }

    /**
     * 是否不为空，为空则抛出异常
     * @param obj 校验的对象
     */
    public static <T> T notNull(T obj) {
        return notNull(obj, ErrorCodeEnum.SERVER_ERROR);
    }

    /**
     * 是否不为空，为空则抛出异常
     * @param obj 校验的对象
     * @param code 抛出异常的错误码
     * @param message 抛出异常的message
     */
    public static <T> T notNull(T obj, String code, String message) {
        return notNull(obj, () -> new APIException(code, message));
    }

    /**
     * 是否不为空，为空则抛出异常
     * @param obj 校验的对象
     * @param message 抛出异常的message
     */
    public static <T> T notNull(T obj, String message) {
        return notNull(obj, "A5000", message);
    }

    /**
     * 校验字符串是否不为空串，为空则抛出指定异常
     * @param str 需要校验字符串
     * @param <X> 抛出的指定异常
     */
    public static <X extends Throwable> String notBlank(String str, Supplier<X> errorSupplier) throws X {
        isFalse(StringUtils.isBlank(str), errorSupplier);
        return str;
    }

    /**
     * 是否不为空串，为空则抛出异常
     * @param str 校验的字符串
     * @param errorCode 错误码枚举
     */
    public static String notBlank(String str, ErrorCodeEnum errorCode) {
        isFalse(StringUtils.isBlank(str), errorCode);
        return str;
    }

    /**
     * 是否不为空串，为空则抛出异常
     * @param str 校验的字符串
     */
    public static String notBlank(String str) {
        return notBlank(str, ErrorCodeEnum.SERVER_ERROR);
    }

    /**
     * 是否不为空串，为空则抛出异常
     * @param str 校验的字符串
     * @param code 抛出异常的错误码
     * @param message 抛出异常的message
     */
    public static String notBlank(String str, String code, String message) {
        return notBlank(str, () -> new APIException(code, message));
    }

    /**
     * 是否不为空串，为空则抛出异常
     * @param str 校验的字符串
     * @param message 抛出异常的message
     */
    public static String notBlank(String str, String message) {
        return notBlank(str, "A5000", message);
    }

    /**
     * 校验集合是否不为空，为空则抛出指定异常
     * @param collection 需要校验集合
     * @param <X> 抛出的指定异常
     */
    public static <E, X extends Throwable> Collection<E> notEmpty(Collection<E> collection, Supplier<X> errorSupplier) throws X {
        isFalse(CollUtils.isEmpty(collection), errorSupplier);
        return collection;
    }

    /**
     * 校验集合是否不为空，为空则抛出异常
     * @param collection 需要校验集合
     * @param errorCode 错误码枚举
     */
    public static <E> Collection<E> notEmpty(Collection<E> collection, ErrorCodeEnum errorCode) {
        isFalse(CollUtils.isEmpty(collection), errorCode);
        return collection;
    }

    /**
     * 校验集合是否不为空，为空则抛出异常
     * @param collection 需要校验集合
     */
    public static <E> Collection<E> notEmpty(Collection<E> collection) {
        return notEmpty(collection, ErrorCodeEnum.SERVER_ERROR);
    }

    /**
     * 校验集合是否不为空，为空则抛出异常
     * @param collection 需要校验集合
     * @param code 抛出异常的错误码
     * @param message 抛出异常的message
     */
    public static <E> Collection<E> notEmpty(Collection<E> collection, String code, String message) {
        return notEmpty(collection, () -> new APIException(code, message));
    }

    /**
     * 校验集合是否不为空，为空则抛出异常
     * @param collection 需要校验集合
     * @param message 抛出异常的message
     */
    public static <E> Collection<E> notEmpty(Collection<E> collection, String message) {
        return notEmpty(collection, "A5000", message);
    }

    /**
     * 校验Map是否不为空，为空则抛出指定异常
     * @param map 需要校验map
     * @param <X> 抛出的指定异常
     */
    public static <K, V, X extends Throwable> Map<K, V> notEmpty(Map<K, V> map, Supplier<X> errorSupplier) throws X {
        isFalse(CollUtils.isEmpty(map), errorSupplier);
        return map;
    }

    /**
     * 校验Map是否不为空，为空则抛出异常
     * @param map 需要校验map
     * @param errorCode 错误码枚举
     */
    public static <K, V> Map<K, V> notEmpty(Map<K, V> map, ErrorCodeEnum errorCode) {
        isFalse(CollUtils.isEmpty(map), errorCode);
        return map;
    }

    /**
     * 校验Map是否不为空，为空则抛出异常
     * @param map 需要校验map
     */
    public static <K, V> Map<K, V> notEmpty(Map<K, V> map) {
        return notEmpty(map, ErrorCodeEnum.SERVER_ERROR);
    }

    /**
     * 校验Map是否不为空，为空则抛出异常
     * @param map 需要校验map
     * @param code 抛出异常的错误码
     * @param message 抛出异常的message
     */
    public static <K, V> Map<K, V> notEmpty(Map<K, V> map, String code, String message) {
        return notEmpty(map, () -> new APIException(code, message));
    }

    /**
     * 校验Map是否不为空，为空则抛出异常
     * @param map 需要校验map
     * @param message 抛出异常的message
     */
    public static <K, V> Map<K, V> notEmpty(Map<K, V> map, String message) {
        return notEmpty(map, "A5000", message);
    }

}
